<template>
  <!-- 定义一个 schema(json) -> form 结构 -> 动态形成 form 表单组件 -->
  <div v-for="(item, index) in schema" :key="index">
    <div class="mb-3" v-if="item.type === 'input'">
      <label for="exampleFormControlInput1" class="form-label">{{ item.field }}</label>
      <input type="text" class="form-control" id="exampleFormControlInput1" :placeholder="item.attr?.placeholder"
        v-model="model[item.prop]">
    </div>
    <!-- <div class="mb-3">
    <label for="exampleFormControlInput1" class="form-label">密码</label>
    <input type="text" class="form-control" id="exampleFormControlInput1" placeholder="请输入登录密码"
      v-model="formValue.password">
  </div> -->
    <div class="mb-3" v-else-if="item.type === 'checkbox'">
      <label class="form-label">{{ item.field }}</label>
      <div>
        <div class="form-check form-check-inline" v-for="(citem, cidx) in item.children" :key="cidx">
          <input class="form-check-input" type="checkbox" :value="citem.value" :id="citem.id"
            v-model="model[item.prop]">
          <label class="form-check-label" :for="citem.id">
            {{ citem.field }}
          </label>
        </div>
        <!-- <div class="form-check form-check-inline">
          <input class="form-check-input" type="checkbox" :value="2" id="flexCheckChecked" v-model="formValue.roles">
          <label class="form-check-label" for="flexCheckChecked">
            普通用户
          </label>
        </div>
        <div class="form-check form-check-inline">
          <input class="form-check-input" type="checkbox" :value="3" id="flex3" v-model="formValue.roles">
          <label class="form-check-label" for="flex3">
            测试用户
          </label>
        </div> -->
      </div>
    </div>
    <div class="mb-3" v-else-if="item.type === 'radio'">
      <label for="exampleFormControlInput1" class="form-label">{{ item.field }}</label>
      <div>
        <div class="form-check form-check-inline" v-for="(ritem, ridx) in item.children" :key="ridx">
          <input class="form-check-input" type="radio" name="flexRadioDefault" :id="ritem.id"
             :value="ritem.value" v-model="model[item.prop]">
          <label class="form-check-label" :for="ritem.id">
            {{ ritem.field }}
          </label>
        </div>
        <!-- <div class="form-check form-check-inline">
          <input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault2"
            v-model="formValue.profile.gender" :value="2">
          <label class="form-check-label" for="flexRadioDefault2">
            女
          </label>
        </div> -->
      </div>
    </div>
    <!-- <div class="mb-3">
    <label for="exampleFormControlInput1" class="form-label">用户头像</label>
    <input type="text" class="form-control" id="exampleFormControlInput1" placeholder="请输入用户头像路径"
      v-model="formValue.profile.photo">
  </div> -->
    <!-- <div class="mb-3">
    <label for="exampleFormControlInput1" class="form-label">地址</label>
    <input type="text" class="form-control" id="exampleFormControlInput1" placeholder="请输入地址"
      v-model="formValue.profile.address">
  </div> -->
  </div>
</template>

<script lang="ts">
import { PropType, defineComponent, ref, watch } from 'vue'
import { cloneDeep } from 'lodash-es'

export interface FormItem {
  field: string;  // label 标签的文本
  type: 'input' | 'checkbox' | 'radio';  // 表单类型
  prop: string;
  attr?: {
    placeholder: string;
  };
  value?: string | number;
  children?: Array<any>
}

export default defineComponent({
  props: {
    schema: {
      type: Array as PropType<FormItem[]>,
      default: () => []
    }
  },
  emits: ['change'],
  // expose: ['clearForm'],
  setup(_props, { emit, expose }) {
    const rand = () => {
      return Math.random().toString(36).substring(2)
    }
    const model = ref<any>({
      ...cloneDeep(_props.schema.reduce((prev, cur) => {
        prev[cur.prop] = cur.value;
        if(['checkbox', 'radio'].includes(cur.type)){
          cur.children?.forEach(o => {
            o.id = rand()
          })
        }
        return prev;
      }, {} as Record<string, any>))
    });


    watch(() => model.value, () => {
      emit('change', model.value)
    }, { deep: true })

    const clearForm = () => {
      model.value = cloneDeep(_props.schema.reduce((prev, cur) => {
        prev[cur.prop] = cur.value;
        return prev;
      }, {} as Record<string, any>))
    }

    expose({ clearForm })
    return {
      model,
      clearForm
    }
  }
})
</script>

<style scoped></style>
